package me.lwn.auth.security.oauth2.server.authorization.authentication;

import me.lwn.auth.security.web.authentication.SmsAuthenticationToken;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.util.Assert;

import java.util.Map;

import static me.lwn.auth.security.utils.Constants.*;

public class OAuth2SmsAuthenticationProvider extends AbstractAuthenticationProvider {

    private static final Logger LOGGER = LogManager.getLogger(OAuth2SmsAuthenticationProvider.class);

    public OAuth2SmsAuthenticationProvider(AuthenticationManager authenticationManager,
                                           OAuth2AuthorizationService authorizationService,
                                           JwtEncoder jwtEncoder) {
        super(authenticationManager, authorizationService, jwtEncoder, new AuthorizationGrantType(SPRING_SECURITY_OAUTH_GRANT_TYPE_SMS_VALUE));
    }

    public final void setJwtCustomizer(OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer) {
        Assert.notNull(jwtCustomizer, "jwtCustomizer cannot be null");
        super.setJwtCustomizer(jwtCustomizer);
    }

    public void setProviderSettings(ProviderSettings providerSettings) {
        super.setProviderSettings(providerSettings);
    }

    @Override
    protected Authentication attemptAuthentication(Authentication authentication) {
        OAuth2SmsAuthenticationToken auth2SmsAuthenticationToken = (OAuth2SmsAuthenticationToken) authentication;

        Map<String, Object> additionalParameters = auth2SmsAuthenticationToken.getAdditionalParameters();
        String mobile = (String) additionalParameters.get(SPRING_SECURITY_OAUTH_FORM_MOBILE_KEY);
        String smsCode = (String) additionalParameters.get(SPRING_SECURITY_OAUTH_FORM_MOBILE_VALUE);
        
        SmsAuthenticationToken smsAuthenticationToken = new SmsAuthenticationToken(mobile, smsCode);
        return authenticationManager.authenticate(smsAuthenticationToken);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        boolean supports = OAuth2SmsAuthenticationToken.class.isAssignableFrom(authentication);
        LOGGER.debug("supports authentication=" + authentication + " returning " + supports);
        return supports;
    }

    protected void doAfterPropertiesSet() {

    }
}
